/**
* @file
* Interface Identification APIs from:
*              RFC 3493: Basic Socket Interface Extensions for IPv6
*                  Section 4: Interface Identification
*/

/*
* Copyright (c) <2013-2015>, <Huawei Technologies Co., Ltd>
* All rights reserved.

* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
*    this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
*    this list of conditions and the following disclaimer in the documentation
*    and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
*    derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
*
*
*/
/* 
* This file contains the implementation for RFC 2553/3493 section Section 4: Interface Identification
* The following functions are implemented 
*  lwip_if_indextoname
*  lwip_if_nametoindex
*  lwip_if_nameindex
*  lwip_if_freenameindex
*  @note: when passing the ifname pointer to the function lwip_if_indextoname:
*  The ifname argument must point to a buffer of at least IF_NAMESIZE   bytes into which the interface name corresponding to the specified
*  index is returned.
*  IF_NAMESIZE is same as IFNAMSIZ and is of 16 bytes including null
*  The lwip_if_nameindex API can only support max 10 interface indexes. The index starts
*  from 1 and ends at 10.
*
*/
#include "lwip/opt.h"
#include "lwip/if.h"

#if LWIP_SOCKET

#include "lwip/netifapi.h"

#if LWIP_SOCKET_SET_ERRNO
#ifndef set_errno
/*lint -e652*/
#define set_errno(err) do { errno = (err); } while(0)
/*lint +e652*/
#endif
#else /* LWIP_SOCKET_SET_ERRNO */
#define set_errno(err)
#endif /* LWIP_SOCKET_SET_ERRNO */

/**
    @page RFC-2553/3493 RFC-2553/3493
 
    @par Compliant Section
    Section 4.1 Name-to-Index
    @par Behavior Description
    if_nametoindex: The  function maps an interface name into its corresponding index.\n
    Behavior:  lwip_if_nametoindex maps an interface name into its corresponding index 
    */ 
/**
    @page RFC-2553/3493 RFC-2553/3493
    
    @par Compliant Section
    Section 4.2 Index-to-Name
    @par Behavior Description
    if_indextoname: The function  maps an interface index into its corresponding name.\n
    Behavior:  lwip_if_indextoname maps an interface index into its corresponding name. When passing  
    the ifname pointer to the function lwip_if_indextoname:The ifname argument must point to a 
    buffer of at least IF_NAMESIZE   bytes into which the interface name corresponding to the specified    
    index is returned.
    */ 
/**
    @page RFC-2553/3493 RFC-2553/3493

    @par Compliant Section
    Section 4.3 Return All Interface Names and Indexes
    @par Behavior Description
    if_nameindex: The function returns an array of if_nameindex structures, one structure per interface.\n
    Behavior:  lwip_if_nameindex is the mapping function for if_nameindex
    */ 
/**
    @page RFC-2553/3493 RFC-2553/3493
 
    @par Compliant Sections
    Section 4.4 Free Memory
    @par Behavior Description
    if_freenameindex: The following function frees the dynamic memory that was allocated by if_nameindex \n
    Behavior:  lwip_if_freenameindex frees the dynamic memory that was allocated by if_freenameindex  
    */ 

/*
 * This function maps an interface index into its corresponding   name.
 *
 * @param ifindex The interface index for which name is required
 * @param ifname The output interface name 
 * @return ifname The output interface name
 *
 */
char *
lwip_if_indextoname(unsigned int ifindex, char *ifname)
{
  err_t err;
  /*Limiting the max index to LWIP_NETIF_IFINDEX_MAX_EX value to keep it aligned to netif_alloc_ifindex
   and as the variable ifindex is a uint8 value*/
  if (ifindex > LWIP_NETIF_IFINDEX_MAX_EX) {
    set_errno(ENXIO);
    return NULL;
  }

  LWIP_ERROR("lwip_if_indextoname:ifname is NULL", (ifname!= NULL) , set_errno(EFAULT); return NULL);

  err = netifapi_netif_index_to_name((u8_t)ifindex, ifname);
  if (!err && ifname[0] != '\0') {
    return ifname;
  }

  set_errno(ENXIO);
  return NULL;
}

/*
 * This function maps an interface name into its corresponding  index.
 *
 * @param ifname The input interface name
 * @return ifindex The output interface index
 *
 */
unsigned int
lwip_if_nametoindex(const char *ifname)
{
  err_t err;
  u8_t uIndex;

  LWIP_ERROR("lwip_if_nametoindex:ifname is NULL", (ifname!= NULL) , set_errno(EFAULT); return 0);

  err = netifapi_netif_name_to_index(ifname, &uIndex);
  if (!err) {
    return uIndex;
  }

  set_errno(ENODEV);
  return 0; /* invalid index */
}

/*
 * This function returns an array of if_nameindex structures, one  structure per interface.
 *
 * @param input None
 * @return if_nameindex*  The array of if_nameindex structures, one structure per interface
 *
 */
struct if_nameindex  *
lwip_if_nameindex(void)
{
    err_t err;
    struct if_nameindex * pifIndexLst = NULL;

    err = netifapi_netif_nameindex_all(&pifIndexLst);
    if (!err && pifIndexLst!=NULL) {
        return pifIndexLst;
    }

    set_errno(ENOBUFS);
    return NULL;
}

/*
 * This function frees the dynamic memory that was allocated by   lwip_if_nameindex().
 *
 * @param if_nameindex* The pointer to if_nameindex structure
 * @return None
 *
 */
void
lwip_if_freenameindex(struct if_nameindex *ptr)
{
    if(ptr == NULL) {
        return;
    }
    mem_free(ptr);
}

#endif /* LWIP_SOCKET */



